Added apis to GtkCellArea for GtkIconView purposes.
authorTristan Van Berkom <tristan.van.berkom@gmail.com>
Sun, 12 Dec 2010 15:18:00 +0000 (00:18 +0900)
committerTristan Van Berkom <tristan.van.berkom@gmail.com>
Sun, 12 Dec 2010 15:29:21 +0000 (00:29 +0900)
Added a few apis,

  - GtkCellAreaContext get_preferred_height_for_width &
    width for height apis and vfuncs, this lets the icon view
    request the collective (and aligned) height for width for
    a said row.

  - gtk_cell_area_copy_context() this creates a duplicate of
    an already created and requested context, this way the icon
    view uses a global context to request the widths of all rows
    and then makes a copy with all the stored alignments and
    uses a separate copy to calculate the height and alignments
    of each row separately.

gtk/gtkcellarea.c
gtk/gtkcellarea.h
gtk/gtkcellareabox.c
gtk/gtkcellareaboxcontext.c
gtk/gtkcellareaboxcontext.h
gtk/gtkcellareacontext.c
gtk/gtkcellareacontext.h

index c21fdcd01364d52859926f1bb42e158d1598ae95..59a1d015d446d0d06dd4bddff6e4456357472bd7 100644 (file)
@@ -1924,6 +1924,46 @@ gtk_cell_area_create_context (GtkCellArea *area)
   return NULL;
 }
 
+/**
+ * gtk_cell_area_copy_context:
+ * @area: a #GtkCellArea
+ * @context: the #GtkCellAreaContext to copy
+ *
+ * This is sometimes needed for cases where rows need to share
+ * alignments in one orientation but may be separately grouped
+ * in the opposing orientation.
+ *
+ * For instance, #GtkIconView creates all icons (rows) to have
+ * the same width and the cells theirin to have the same
+ * horizontal alignments. However each row of icons may have
+ * a separate collective height. #GtkIconView uses this to
+ * request the heights of each row based on a context which
+ * was already used to request all the row widths that are
+ * to be displayed.
+ *
+ * Return value: (transfer full): a newly created #GtkCellAreaContext copy of @context.
+ *
+ * Since: 3.0
+ */
+GtkCellAreaContext *
+gtk_cell_area_copy_context (GtkCellArea        *area,
+                           GtkCellAreaContext *context)
+{
+  GtkCellAreaClass *class;
+
+  g_return_val_if_fail (GTK_IS_CELL_AREA (area), NULL);
+  g_return_val_if_fail (GTK_IS_CELL_AREA_CONTEXT (context), NULL);
+
+  class = GTK_CELL_AREA_GET_CLASS (area);
+
+  if (class->copy_context)
+    return class->copy_context (area, context);
+
+  g_warning ("GtkCellAreaClass::copy_context not implemented for `%s'", 
+            g_type_name (G_TYPE_FROM_INSTANCE (area)));
+  
+  return NULL;
+}
 
 /**
  * gtk_cell_area_get_request_mode:
index 8c54b053d290de1b8b1f7ccf22d8085d0c2c4f29..61579221fb30ed7e3c036a3caa08caef37986e59 100644 (file)
@@ -202,6 +202,8 @@ struct _GtkCellAreaClass
 
   /* Geometry */
   GtkCellAreaContext *(* create_context)                 (GtkCellArea             *area);
+  GtkCellAreaContext *(* copy_context)                   (GtkCellArea             *area,
+                                                         GtkCellAreaContext      *context);
   GtkSizeRequestMode (* get_request_mode)                (GtkCellArea             *area);
   void               (* get_preferred_width)             (GtkCellArea             *area,
                                                          GtkCellAreaContext      *context,
@@ -316,6 +318,8 @@ GtkCellRenderer      *gtk_cell_area_get_cell_at_position           (GtkCellArea
 
 /* Geometry */
 GtkCellAreaContext   *gtk_cell_area_create_context                 (GtkCellArea        *area);
+GtkCellAreaContext   *gtk_cell_area_copy_context                   (GtkCellArea        *area,
+                                                                   GtkCellAreaContext *context);
 GtkSizeRequestMode    gtk_cell_area_get_request_mode               (GtkCellArea        *area);
 void                  gtk_cell_area_get_preferred_width            (GtkCellArea        *area,
                                                                    GtkCellAreaContext *context,
index 286c67096da45436809883cda117807baa759a8a..56a856bf6a22461f2242b5fc42518d8d90207948 100644 (file)
@@ -92,6 +92,8 @@ static void      gtk_cell_area_box_get_cell_property              (GtkCellArea
                                                                   GValue               *value,
                                                                   GParamSpec           *pspec);
 static GtkCellAreaContext *gtk_cell_area_box_create_context       (GtkCellArea          *area);
+static GtkCellAreaContext *gtk_cell_area_box_copy_context         (GtkCellArea          *area,
+                                                                  GtkCellAreaContext   *context);
 static GtkSizeRequestMode  gtk_cell_area_box_get_request_mode     (GtkCellArea          *area);
 static void      gtk_cell_area_box_get_preferred_width            (GtkCellArea          *area,
                                                                   GtkCellAreaContext   *context,
@@ -273,6 +275,7 @@ gtk_cell_area_box_class_init (GtkCellAreaBoxClass *class)
   area_class->get_cell_property   = gtk_cell_area_box_get_cell_property;
   
   area_class->create_context                 = gtk_cell_area_box_create_context;
+  area_class->copy_context                   = gtk_cell_area_box_copy_context;
   area_class->get_request_mode               = gtk_cell_area_box_get_request_mode;
   area_class->get_preferred_width            = gtk_cell_area_box_get_preferred_width;
   area_class->get_preferred_height           = gtk_cell_area_box_get_preferred_height;
@@ -1301,6 +1304,23 @@ gtk_cell_area_box_create_context (GtkCellArea *area)
   return context;
 }
 
+static GtkCellAreaContext *
+gtk_cell_area_box_copy_context (GtkCellArea        *area,
+                               GtkCellAreaContext *context)
+{
+  GtkCellAreaBox        *box  = GTK_CELL_AREA_BOX (area);
+  GtkCellAreaBoxPrivate *priv = box->priv;
+  GtkCellAreaContext    *copy = 
+    (GtkCellAreaContext *)gtk_cell_area_box_context_copy (GTK_CELL_AREA_BOX (area), 
+                                                         GTK_CELL_AREA_BOX_CONTEXT (context));
+
+  priv->contexts = g_slist_prepend (priv->contexts, copy);
+
+  g_object_weak_ref (G_OBJECT (copy), (GWeakNotify)context_weak_notify, box);
+
+  return copy;
+}
+
 static GtkSizeRequestMode 
 gtk_cell_area_box_get_request_mode (GtkCellArea *area)
 {
index cc4c0b4c4857dcf284d48f15f1aab84758a13772..fbf6ffea1d8fe7fc8add4abe47969455b8bd520b 100644 (file)
@@ -35,10 +35,23 @@ static void      gtk_cell_area_box_context_reset                 (GtkCellAreaCon
 static void      gtk_cell_area_box_context_allocate              (GtkCellAreaContext    *context,
                                                                  gint                   width,
                                                                  gint                   height);
+static void      gtk_cell_area_box_context_get_preferred_height_for_width (GtkCellAreaContext *context,
+                                                                          gint                width,
+                                                                          gint               *minimum_height,
+                                                                          gint               *natural_height);
+static void      gtk_cell_area_box_context_get_preferred_width_for_height (GtkCellAreaContext *context,
+                                                                          gint                height,
+                                                                          gint               *minimum_width,
+                                                                          gint               *natural_width);
+
+
 
 /* Internal functions */
-static void      gtk_cell_area_box_context_sum                   (GtkCellAreaBoxContext *context,
-                                                                 GtkOrientation         orientation);
+static void      gtk_cell_area_box_context_sum                  (GtkCellAreaBoxContext  *context,
+                                                                GtkOrientation          orientation,
+                                                                gint                    for_size,
+                                                                gint                   *minimum_size,
+                                                                gint                   *natural_size);
 static void      free_cache_array                                (GArray                *array);
 static GArray   *group_array_new                                 (GtkCellAreaBoxContext *context);
 static GArray   *get_array                                       (GtkCellAreaBoxContext *context,
@@ -190,8 +203,10 @@ gtk_cell_area_box_context_class_init (GtkCellAreaBoxContextClass *class)
   /* GObjectClass */
   object_class->finalize = gtk_cell_area_box_context_finalize;
 
-  context_class->reset     = gtk_cell_area_box_context_reset;
-  context_class->allocate  = gtk_cell_area_box_context_allocate;
+  context_class->reset                          = gtk_cell_area_box_context_reset;
+  context_class->allocate                       = gtk_cell_area_box_context_allocate;
+  context_class->get_preferred_height_for_width = gtk_cell_area_box_context_get_preferred_height_for_width;
+  context_class->get_preferred_width_for_height = gtk_cell_area_box_context_get_preferred_width_for_height;
 
   g_type_class_add_private (object_class, sizeof (GtkCellAreaBoxContextPrivate));
 }
@@ -402,7 +417,10 @@ gtk_cell_area_box_context_allocate (GtkCellAreaContext *context,
 
 static void
 gtk_cell_area_box_context_sum (GtkCellAreaBoxContext *context,
-                              GtkOrientation         orientation)
+                              GtkOrientation         orientation,
+                              gint                   for_size,
+                              gint                  *minimum_size,
+                              gint                  *natural_size)
 {
   GtkCellArea    *area;
   GtkOrientation  box_orientation;
@@ -413,7 +431,7 @@ gtk_cell_area_box_context_sum (GtkCellAreaBoxContext *context,
   area            = gtk_cell_area_context_get_area (GTK_CELL_AREA_CONTEXT (context));
   spacing         = gtk_cell_area_box_get_spacing (GTK_CELL_AREA_BOX (area));
   box_orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (area));
-  array           = get_array (context, orientation, -1);
+  array           = get_array (context, orientation, for_size);
 
   for (i = 0; i < array->len; i++)
     {
@@ -440,15 +458,100 @@ gtk_cell_area_box_context_sum (GtkCellAreaBoxContext *context,
        }
     }
 
-  if (orientation == GTK_ORIENTATION_HORIZONTAL)
-    gtk_cell_area_context_push_preferred_width (GTK_CELL_AREA_CONTEXT (context), min_size, nat_size);
-  else
-    gtk_cell_area_context_push_preferred_height (GTK_CELL_AREA_CONTEXT (context), min_size, nat_size);
+  if (for_size < 0)
+    {
+      if (orientation == GTK_ORIENTATION_HORIZONTAL)
+       gtk_cell_area_context_push_preferred_width (GTK_CELL_AREA_CONTEXT (context), min_size, nat_size);
+      else
+       gtk_cell_area_context_push_preferred_height (GTK_CELL_AREA_CONTEXT (context), min_size, nat_size);
+    }
+
+  if (minimum_size)
+    *minimum_size = min_size;
+  if (natural_size)
+    *natural_size = nat_size;
+}
+
+static void
+gtk_cell_area_box_context_get_preferred_height_for_width (GtkCellAreaContext *context,
+                                                         gint                width,
+                                                         gint               *minimum_height,
+                                                         gint               *natural_height)
+{
+  gtk_cell_area_box_context_sum (GTK_CELL_AREA_BOX_CONTEXT (context), GTK_ORIENTATION_VERTICAL, 
+                                width, minimum_height, natural_height);
+}
+
+static void
+gtk_cell_area_box_context_get_preferred_width_for_height (GtkCellAreaContext *context,
+                                                         gint                height,
+                                                         gint               *minimum_width,
+                                                         gint               *natural_width)
+{
+  gtk_cell_area_box_context_sum (GTK_CELL_AREA_BOX_CONTEXT (context), GTK_ORIENTATION_HORIZONTAL, 
+                                height, minimum_width, natural_width);
 }
 
 /*************************************************************
  *                            API                            *
  *************************************************************/
+static void
+copy_size_array (GArray *src_array,
+                GArray *dest_array)
+{
+  gint i;
+
+  for (i = 0; i < src_array->len; i++)
+    {
+      CachedSize *src  = &g_array_index (src_array, CachedSize, i);
+      CachedSize *dest = &g_array_index (dest_array, CachedSize, i);
+
+      memcpy (dest, src, sizeof (CachedSize));
+    }
+}
+
+static void
+for_size_copy (gpointer    key,
+              GArray     *size_array,
+              GHashTable *dest_hash)
+{
+  GArray *new_array;
+
+  new_array = g_array_new (FALSE, TRUE, sizeof (CachedSize));
+  g_array_set_size (new_array, size_array->len);
+
+  copy_size_array (size_array, new_array);
+
+  g_hash_table_insert (dest_hash, key, new_array);
+}
+
+GtkCellAreaBoxContext *
+gtk_cell_area_box_context_copy (GtkCellAreaBox        *box,
+                               GtkCellAreaBoxContext *box_context)
+{
+  GtkCellAreaBoxContext *context;
+
+  context = g_object_new (GTK_TYPE_CELL_AREA_BOX_CONTEXT, 
+                         "area", box, NULL);
+
+  gtk_cell_area_box_init_groups (context, 
+                                box_context->priv->base_widths->len,
+                                box_context->priv->expand);
+
+  /* Copy all the arrays */
+  copy_size_array (box_context->priv->base_widths, 
+                  context->priv->base_widths);
+  copy_size_array (box_context->priv->base_heights, 
+                  context->priv->base_heights);
+
+  g_hash_table_foreach (box_context->priv->heights,
+                       (GHFunc)for_size_copy, context->priv->heights);
+  g_hash_table_foreach (box_context->priv->widths,
+                       (GHFunc)for_size_copy, context->priv->widths);
+
+  return context;
+}
+
 void
 gtk_cell_area_box_init_groups (GtkCellAreaBoxContext *box_context,
                               guint                  n_groups,
@@ -500,7 +603,7 @@ gtk_cell_area_box_context_push_group_width (GtkCellAreaBoxContext *box_context,
     }
 
   if (grew)
-    gtk_cell_area_box_context_sum (box_context, GTK_ORIENTATION_HORIZONTAL);
+    gtk_cell_area_box_context_sum (box_context, GTK_ORIENTATION_HORIZONTAL, -1, NULL, NULL);
 }
 
 void
@@ -559,7 +662,7 @@ gtk_cell_area_box_context_push_group_height (GtkCellAreaBoxContext *box_context,
     }
 
   if (grew)
-    gtk_cell_area_box_context_sum (box_context, GTK_ORIENTATION_VERTICAL);
+    gtk_cell_area_box_context_sum (box_context, GTK_ORIENTATION_VERTICAL, -1, NULL, NULL);
 }
 
 void
index 7800b0fdcb94624da18fb91f53c006509906a9a9..1161d38b2f647b39a2d82223c0a8a3bfe67f3696 100644 (file)
@@ -62,6 +62,10 @@ struct _GtkCellAreaBoxContextClass
 GType   gtk_cell_area_box_context_get_type                     (void) G_GNUC_CONST;
 
 
+/* Create a duplicate of the context */
+GtkCellAreaBoxContext *gtk_cell_area_box_context_copy          (GtkCellAreaBox        *box,
+                                                               GtkCellAreaBoxContext *box_context);
+
 /* Initialize group array dimensions */
 void    gtk_cell_area_box_init_groups                          (GtkCellAreaBoxContext *box_context,
                                                                guint                  n_groups,
index 087b590401b44efa9d87560824a7e934968dfe1d..f3c14b00ddf84fa97cacec4a00ac15c9ef026c24 100644 (file)
@@ -489,6 +489,66 @@ gtk_cell_area_context_get_preferred_height (GtkCellAreaContext *context,
     *natural_height = priv->nat_height;
 }
 
+/**
+ * gtk_cell_area_context_get_preferred_height_for_width:
+ * @context: a #GtkCellAreaContext
+ * @width: a proposed width for allocation
+ * @minimum_height: (out) (allow-none): location to store the minimum height, or %NULL
+ * @natural_height: (out) (allow-none): location to store the natural height, or %NULL
+ *
+ * Gets the accumulative preferred height for @width for all rows which have been 
+ * requested for the same said @width with this context.
+ *
+ * After gtk_cell_area_context_reset() is called and/or before ever requesting
+ * the size of a #GtkCellArea, the returned values are -1.
+ *
+ * Since: 3.0
+ */
+void
+gtk_cell_area_context_get_preferred_height_for_width (GtkCellAreaContext *context,
+                                                     gint                width,
+                                                     gint               *minimum_height,
+                                                     gint               *natural_height)
+{
+  g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
+
+  if (GTK_CELL_AREA_CONTEXT_GET_CLASS (context)->get_preferred_height_for_width)
+    GTK_CELL_AREA_CONTEXT_GET_CLASS (context)->get_preferred_height_for_width (context,
+                                                                              width,
+                                                                              minimum_height,
+                                                                              natural_height);
+}
+
+/**
+ * gtk_cell_area_context_get_preferred_width_for_height:
+ * @context: a #GtkCellAreaContext
+ * @height: a proposed height for allocation
+ * @minimum_width: (out) (allow-none): location to store the minimum width, or %NULL
+ * @natural_width: (out) (allow-none): location to store the natural width, or %NULL
+ *
+ * Gets the accumulative preferred width for @height for all rows which have 
+ * been requested for the same said @height with this context.
+ *
+ * After gtk_cell_area_context_reset() is called and/or before ever requesting
+ * the size of a #GtkCellArea, the returned values are -1.
+ *
+ * Since: 3.0 
+ */
+void
+gtk_cell_area_context_get_preferred_width_for_height (GtkCellAreaContext *context,
+                                                     gint                height,
+                                                     gint               *minimum_width,
+                                                     gint               *natural_width)
+{  
+  g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
+
+  if (GTK_CELL_AREA_CONTEXT_GET_CLASS (context)->get_preferred_width_for_height)
+    GTK_CELL_AREA_CONTEXT_GET_CLASS (context)->get_preferred_width_for_height (context,
+                                                                              height,
+                                                                              minimum_width,
+                                                                              natural_width);
+}
+
 /**
  * gtk_cell_area_context_get_allocation:
  * @context: a #GtkCellAreaContext
index 2731a73db41048de932e96957044e3b5d51765c2..d2b462cfce0c9a35a7422e0d4f107d0496e369cc 100644 (file)
@@ -65,10 +65,18 @@ struct _GtkCellAreaContextClass
   GObjectClass parent_class;
 
   /*< public >*/
-  void    (* allocate)               (GtkCellAreaContext *context,
-                                     gint                width,
-                                     gint                height);
-  void    (* reset)                  (GtkCellAreaContext *context);
+  void    (* allocate)                       (GtkCellAreaContext *context,
+                                             gint                width,
+                                             gint                height);
+  void    (* reset)                          (GtkCellAreaContext *context);
+  void    (* get_preferred_height_for_width) (GtkCellAreaContext *context,
+                                             gint                width,
+                                             gint               *minimum_height,
+                                             gint               *natural_height);
+  void    (* get_preferred_width_for_height) (GtkCellAreaContext *context,
+                                             gint                height,
+                                             gint               *minimum_width,
+                                             gint               *natural_width);
 
   /*< private >*/
   /* Padding for future expansion */
@@ -81,22 +89,30 @@ struct _GtkCellAreaContextClass
 GType        gtk_cell_area_context_get_type              (void) G_GNUC_CONST;
 
 /* Main apis */
-GtkCellArea *gtk_cell_area_context_get_area              (GtkCellAreaContext *context);
-void         gtk_cell_area_context_allocate              (GtkCellAreaContext *context,
-                                                         gint                width,
-                                                         gint                height);
-void         gtk_cell_area_context_reset                 (GtkCellAreaContext *context);
+GtkCellArea *gtk_cell_area_context_get_area                        (GtkCellAreaContext *context);
+void         gtk_cell_area_context_allocate                        (GtkCellAreaContext *context,
+                                                                   gint                width,
+                                                                   gint                height);
+void         gtk_cell_area_context_reset                           (GtkCellAreaContext *context);
 
 /* Apis for GtkCellArea clients to consult cached values for a series of GtkTreeModel rows */
-void         gtk_cell_area_context_get_preferred_width   (GtkCellAreaContext *context,
-                                                         gint               *minimum_width,
-                                                         gint               *natural_width);
-void         gtk_cell_area_context_get_preferred_height  (GtkCellAreaContext *context,
-                                                         gint               *minimum_height,
-                                                         gint               *natural_height);
-void         gtk_cell_area_context_get_allocation        (GtkCellAreaContext *context,
-                                                         gint               *width,
-                                                         gint               *height);
+void         gtk_cell_area_context_get_preferred_width            (GtkCellAreaContext *context,
+                                                                  gint               *minimum_width,
+                                                                  gint               *natural_width);
+void         gtk_cell_area_context_get_preferred_height           (GtkCellAreaContext *context,
+                                                                  gint               *minimum_height,
+                                                                  gint               *natural_height);
+void         gtk_cell_area_context_get_preferred_height_for_width (GtkCellAreaContext *context,
+                                                                  gint                width,
+                                                                  gint               *minimum_height,
+                                                                  gint               *natural_height);
+void         gtk_cell_area_context_get_preferred_width_for_height (GtkCellAreaContext *context,
+                                                                  gint                height,
+                                                                  gint               *minimum_width,
+                                                                  gint               *natural_width);
+void         gtk_cell_area_context_get_allocation                 (GtkCellAreaContext *context,
+                                                                  gint               *width,
+                                                                  gint               *height);
 
 /* Apis for GtkCellArea implementations to update cached values for multiple GtkTreeModel rows */
 void         gtk_cell_area_context_push_preferred_width  (GtkCellAreaContext *context,